import 'dart:async';
import 'package:flutter/material.dart';

enum TopicChannel {
  initial,
  docs,
  metrics,
}

class Topic {
  TopicChannel channel = TopicChannel.initial;
  Object? value;
}

class TopicCenter {
  static final TopicCenter _instance = TopicCenter._();
  final _streamController = StreamController<Topic>.broadcast();
  Map<TopicChannel, StreamSubscription> _subscribers = {};

  TopicCenter._();
  factory TopicCenter() => _instance;

  void send(Topic topic) {
    _streamController.sink.add(topic);
  }

  void listen<T>(
    ValueSetter<T> valueSetter, {
    TopicChannel onChannel = TopicChannel.initial,
  }) {
    if (_subscribers.containsKey(onChannel)) {
      return;
    }
    _subscribers[onChannel] = _streamController.stream
        .where((topic) => topic.channel == onChannel)
        .listen((topic) {
      valueSetter(topic.value as T);
    }, onError: (e, s) {
      print('TopicCenter listen \n e: ${e.toString()} \n s: ${s.toString()}');
    });
  }

  void remove(TopicChannel channel) {
    _subscribers[channel]?.cancel();
    _subscribers.remove(channel);
  }

  void dispose() {
    _subscribers.forEach((key, value) {
      value.cancel();
    });
    _subscribers = {};
    _streamController.close();
  }
}
